package com.xsomnus.data_structures;

/**
 * @author @叶小夏
 * @since 2019/7/31 0031 9:47
 * - 才需学也,学需静也/非淡泊无以明志，非宁静无以致远
 * 环形缓冲区
 */
public class CircularByteBuffer22 {

    private static final int DEFAULT_CAPACITY = 10;

    // 不知道结束符用什么标识，暂时就先用*代替
    private static final byte END_FLAG = '*';

    /**
     * 容量
     */
    private int capacity;
    /**
     * 底层的静态数据，用户存放数据
     */
    private byte[] data;

    /**
     * 读索引
     */
    private int readIndex;
    /**
     * 写索引
     */
    private int writeIndex;

    /**
     * 写索引最多比读操作多一个capacity
     */
    private boolean loop;

    public CircularByteBuffer22() {
        this.capacity = DEFAULT_CAPACITY;
        this.data = new byte[capacity];
    }

    private CircularByteBuffer22(int capacity) {
        this.capacity = capacity;
        this.data = new byte[capacity];
    }

    /**
     * 写数据
     */
    public void write(byte[] bytes) {
        int len = bytes.length;
        if (len > writableBytes()) {
            throw new IllegalArgumentException("no sufficient space to write, left write space is " + writableBytes());
        }
        if (writeIndex + len > capacity) {
            int left = capacity - writeIndex;
            loop = true;
            System.arraycopy(bytes, 0, data, writeIndex, left);
            System.arraycopy(bytes, left, data, 0, len - left);
            writeIndex = (writeIndex + len) % capacity;
        } else {
            System.arraycopy(bytes, 0, data, writeIndex, bytes.length);
            writeIndex = writeIndex + bytes.length;
        }
    }

    /**
     * 读数据
     */
    public byte[] read(int length) {
        if (length > readableBytes()) {
            throw new IndexOutOfBoundsException("length is to big and no sufficient data for read");
        }
        byte[] ret = new byte[length];

        if (readIndex + length > capacity) {
            final int leftLen = capacity - readIndex;
            loop = false;
            System.arraycopy(data, readIndex, ret, 0, leftLen);
            System.arraycopy(data, 0, ret, leftLen, length - leftLen);
        } else {
            System.arraycopy(data, readIndex, ret, 0, length);
        }
        readIndex = (readIndex + length) % capacity;
        return ret;
    }


    /**
     * 可读的字节数
     */
    public int readableBytes() {
        return loop ? (capacity + writeIndex - readIndex) : writeIndex - readIndex;
    }

    public int writableBytes() {
        return loop ? (readIndex - writeIndex) : (capacity - writeIndex + readIndex);
    }

    public int getCapacity() {
        return capacity;
    }

    public int getReadIndex() {
        return readIndex;
    }

    public int getWriteIndex() {
        return writeIndex;
    }
}
